/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package ly.count.ohos.demo;

import ly.count.ohos.sdk.Countly;
import ly.count.ohos.sdk.ModuleFeedback;
import ly.count.ohos.sdk.StarRatingCallback;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ScrollView;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
import ohos.global.configuration.Configuration;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 反馈示例页面
 *
 * @since 2021-04-13
 */
public class AbilityExampleFeedback extends Ability {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, Countly.TAG);
    private static final String CLOSE_BTN_TEXT = "Close";
    private static final String EMPTY_LIST = "Got a null widget list";
    private static final String STRING_ERROR_PRE = "Encountered error while getting ";
    private static final String STRING_ERROR_END = " ]";

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_ability_example_feedback);
        findComponentById(ResourceTable.Id_button42).setClickedListener(this::onClickViewOther02);
        findComponentById(ResourceTable.Id_button46).setClickedListener(this::onClickViewOther07);
        findComponentById(ResourceTable.Id_button71).setClickedListener(this::onClickSendManualRating);
        findComponentById(ResourceTable.Id_button63).setClickedListener(this::onClickShowSurvey);
        findComponentById(ResourceTable.Id_button69).setClickedListener(this::onClickShowNps);
        findComponentById(ResourceTable.Id_button61).setClickedListener(this::onClickReportSurveyManually);
        findComponentById(ResourceTable.Id_button62).setClickedListener(this::onClickReportNpsManually);
        Countly.sharedInstance().onStart(this);

        ScrollView scrollView = (ScrollView) findComponentById(ResourceTable.Id_feed_back_scroll_view);
        scrollView.enableScrollBar(ScrollView.AXIS_Y, true);
    }

    @Override
    public void onStop() {
        Countly.sharedInstance().onStop();
        super.onStop();
    }

    private void onClickViewOther02(Component v) {
        // show star rating
        Countly.sharedInstance().ratings().showStarRating(this, new StarRatingCallback() {
            @Override
            public void onRate(int rating) {
                new ToastDialog(AbilityExampleFeedback.this).setText("onRate called with rating: " + rating).show();
            }

            @Override
            public void onDismiss() {
                new ToastDialog(AbilityExampleFeedback.this).setText("onDismiss called").show();
            }
        });
    }

    private void onClickViewOther07(Component v) {
        // show rating widget
        String widgetId = "5f8c8cfd69ecabb38ed3677a";
        Countly.sharedInstance().ratings().showFeedbackPopup(widgetId, CLOSE_BTN_TEXT,
            AbilityExampleFeedback.this, error -> {
                if (error != null) {
                    showToastDialog("Encountered error while showing feedback dialog: [" + error + STRING_ERROR_END);
                }
            });
    }

    private void onClickSendManualRating(Component v) {
        // record rating manually without showing any UI
        String widgetId = "5f15c01425f83c169c33cb65";
        final int rating = 3;
        ohos.global.resource.ResourceManager resManager = this.getResourceManager();

        try {
            String result = resManager.getElement(ResourceTable.String_rate_report_email).getString();
            Countly.sharedInstance().ratings().recordManualRating(widgetId, rating,
                result, "Ragnaros should watch out", true);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        }
    }

    private void onClickShowSurvey(Component v) {
        Countly.sharedInstance().feedback().getAvailableFeedbackWidgets(new ModuleFeedback.RetrieveFeedbackWidgets() {
            @Override
            public void onFinished(List<ModuleFeedback.CountlyFeedbackWidget> retrievedWidgets, String error) {
                if (error != null) {
                    showToastDialog(STRING_ERROR_PRE
                        + "a list of available feedback widgets: ["
                        + error + STRING_ERROR_END);
                    return;
                }
                if (retrievedWidgets == null) {
                    showToastDialog(EMPTY_LIST);
                    return;
                }
                ModuleFeedback.CountlyFeedbackWidget chosenWidget = null;
                for (ModuleFeedback.CountlyFeedbackWidget widget : retrievedWidgets) {
                    if (widget.type == ModuleFeedback.FeedbackWidgetType.survey) {
                        chosenWidget = widget;
                        break;
                    }
                }

                if (chosenWidget == null) {
                    new ToastDialog(AbilityExampleFeedback.this).setText("No available Survey widget").show();
                    return;
                }

                Countly.sharedInstance().feedback().presentFeedbackWidget(chosenWidget, AbilityExampleFeedback.this,
                    CLOSE_BTN_TEXT, new ModuleFeedback.FeedbackCallback() {
                        @Override
                        public void onFinished(String error) {
                            if (error != null) {
                                new ToastDialog(AbilityExampleFeedback.this)
                                    .setText("Encountered error while presenting "
                                        + "the feedback widget: [" + error + STRING_ERROR_END)
                                    .show();
                            }
                        }
                    });
            }
        });
    }

    private void onClickShowNps(Component v) {
        Countly.sharedInstance().feedback().getAvailableFeedbackWidgets(
            new ModuleFeedback.RetrieveFeedbackWidgets() {
                @Override
                public void onFinished(List<ModuleFeedback.CountlyFeedbackWidget> retrievedWidgets, String error) {
                    if (error != null) {
                        showToastDialog(STRING_ERROR_PRE
                            + "a list of available feedback widgets: ["
                            + error + STRING_ERROR_END);
                        return;
                    }
                    if (retrievedWidgets == null) {
                        showToastDialog(EMPTY_LIST);
                        return;
                    }
                    ModuleFeedback.CountlyFeedbackWidget chosenWidget = null;
                    for (ModuleFeedback.CountlyFeedbackWidget widget : retrievedWidgets) {
                        if (widget.type == ModuleFeedback.FeedbackWidgetType.nps) {
                            chosenWidget = widget;
                            break;
                        }
                    }
                    if (chosenWidget == null) {
                        new ToastDialog(AbilityExampleFeedback.this).setText("No available NPS widget").show();
                        return;
                    }
                    Countly.sharedInstance().feedback().presentFeedbackWidget(chosenWidget,
                        AbilityExampleFeedback.this, CLOSE_BTN_TEXT, new ModuleFeedback.FeedbackCallback() {
                            @Override
                            public void onFinished(String error) {
                                if (error != null) {
                                    new ToastDialog(AbilityExampleFeedback.this)
                                        .setText("Encountered error while "
                                            + "presenting the feedback widget: ["
                                            + error + STRING_ERROR_END)
                                        .show();
                                }
                            }
                        });
                }
            });
    }

    private void onClickReportNpsManually(Component v) {
        Countly.sharedInstance().feedback().getAvailableFeedbackWidgets(new ModuleFeedback.RetrieveFeedbackWidgets() {
            @Override
            public void onFinished(List<ModuleFeedback.CountlyFeedbackWidget> retrievedWidgets, String error) {
                if (error != null) {
                    showToastDialog(STRING_ERROR_PRE + "a list of available feedback widgets"
                        + " for manual nps report: [" + error + STRING_ERROR_END);
                    return;
                }

                if (retrievedWidgets == null) {
                    showToastDialog(EMPTY_LIST);
                    return;
                }

                ModuleFeedback.CountlyFeedbackWidget chosenWidget = null;
                for (ModuleFeedback.CountlyFeedbackWidget widget : retrievedWidgets) {
                    if (widget.type == ModuleFeedback.FeedbackWidgetType.nps) {
                        chosenWidget = widget;
                        break;
                    }
                }

                if (chosenWidget == null) {
                    new ToastDialog(AbilityExampleFeedback.this)
                        .setText("No available NPS widget for manual reporting").show();
                    return;
                }

                final ModuleFeedback.CountlyFeedbackWidget widgetToReport = chosenWidget;

                Countly.sharedInstance().feedback()
                    .getFeedbackWidgetData(chosenWidget, new ModuleFeedback.RetrieveFeedbackWidgetData() {
                        @Override
                        public void onFinished(JSONObject retrievedWidgetData, String error) {
                            if (error != null) {
                                new ToastDialog(AbilityExampleFeedback.this).setText("Encountered error"
                                    + " while reporting nps feedback widget: [" + error + "]").show();
                                return;
                            }
                            HiLog.debug(LABEL, "Retrieved nps widget data: " + retrievedWidgetData.toString());
                            Map<String, Object> segm = new HashMap<>();
                            final int value = 3;
                            segm.put("rating", value);
                            segm.put("comment", "Filled out comment");
                            Countly.sharedInstance().feedback()
                                .reportFeedbackWidgetManually(widgetToReport, retrievedWidgetData, segm);

                            new ToastDialog(AbilityExampleFeedback.this)
                                .setText("NPS feedback reported manually").show();
                        }
                    });
            }
        });
    }

    private void onClickReportSurveyManually(Component v) {
        ModuleFeedback.RetrieveFeedbackWidgets callback = new ModuleFeedback.RetrieveFeedbackWidgets() {
            @Override
            public void onFinished(List<ModuleFeedback.CountlyFeedbackWidget> retrievedWidgets, String error) {
                if (error != null) {
                    showToastDialog("Encountered error while getting a"
                        + " list of available feedback widgets for "
                        + "manual survey report: [" + error + STRING_ERROR_END);
                    return;
                }
                if (retrievedWidgets == null) {
                    showToastDialog(EMPTY_LIST);
                    return;
                }
                ModuleFeedback.CountlyFeedbackWidget chosenWidget = null;
                for (ModuleFeedback.CountlyFeedbackWidget widget : retrievedWidgets) {
                    if (widget.type == ModuleFeedback.FeedbackWidgetType.survey) {
                        chosenWidget = widget;
                        break;
                    }
                }
                if (chosenWidget == null) {
                    new ToastDialog(AbilityExampleFeedback.this)
                        .setText("No available survey widget for manual reporting").show();
                    return;
                }
                getFeedbackData(chosenWidget);
            }
        };
        Countly.sharedInstance().feedback().getAvailableFeedbackWidgets(callback);
    }

    private void getFeedbackData(ModuleFeedback.CountlyFeedbackWidget chosenWidget) {
        final ModuleFeedback.CountlyFeedbackWidget widgetToReport = chosenWidget;
        ModuleFeedback.RetrieveFeedbackWidgetData callback =
            new ModuleFeedback.RetrieveFeedbackWidgetData() {
                @Override
                public void onFinished(JSONObject retrievedWidgetData, String error) {
                    if (error != null) {
                        new ToastDialog(AbilityExampleFeedback.this)
                            .setText("Encountered error while reporting survey "
                                + "feedback widget: [" + error + STRING_ERROR_END).show();
                        return;
                    }
                    HiLog.info(LABEL, "Retrieved survey widget data: " + retrievedWidgetData.toString());
                    JSONArray questions = retrievedWidgetData.optJSONArray("questions");
                    if (questions == null) {
                        new ToastDialog(AbilityExampleFeedback.this)
                            .setText("No questions found in retrieved survey data").show();
                        return;
                    }
                    Map<String, Object> segm = getStringObjectMap(questions);
                    Countly.sharedInstance().feedback()
                        .reportFeedbackWidgetManually(widgetToReport, retrievedWidgetData, segm);
                    new ToastDialog(AbilityExampleFeedback.this)
                        .setText("Survey feedback reported manually").show();
                }
            };
        Countly.sharedInstance().feedback().getFeedbackWidgetData(chosenWidget, callback);
    }

    private Map<String, Object> getStringObjectMap(JSONArray questions) {
        Map<String, Object> segm = new HashMap<>();
        for (int cur = 0; cur < questions.length(); cur++) {
            JSONObject question = null;
            try {
                question = questions.getJSONObject(cur);
            } catch (JSONException e) {
                HiLog.error(LABEL, e.getMessage());
            }
            String wtype = question.optString("type");
            String questionId = question.optString("id");
            String answerKey = "answ-" + questionId;
            JSONArray choices = question.optJSONArray("choices");
            switch (wtype) {
                case "multi": // multiple answer question
                    StringBuilder sb = new StringBuilder();
                    final int temp = 2;
                    for (int cur2 = 0; cur2 < choices.length(); cur2++) {
                        if (cur2 % temp == 0) {
                            if (cur2 != 0) {
                                sb.append(",");
                            }
                            sb.append(choices.optJSONObject(cur).optString("key"));
                        }
                    }
                    segm.put(answerKey, sb.toString());
                    break;
                case "radio": // radio buttons, dropdown value selector
                case "dropdown":
                    int pick = (int) (Math.random() * choices.length());
                    segm.put(answerKey, choices.optJSONObject(pick).optString("key"));
                    break;
                case "text": // text input field
                    segm.put(answerKey, "Some random text");
                    break;
                case "rating": // rating picker
                    final int bound = 11;
                    segm.put(answerKey, (int) (Math.random() * bound));
                    break;
                default:
                    break;
            }
        }
        return segm;
    }

    @Override
    public void onConfigurationUpdated(Configuration newConfig) {
        super.onConfigurationUpdated(newConfig);
        Countly.sharedInstance().onConfigurationChanged(newConfig);
    }

    /**
     * 弹出ToastDialog
     *
     * @param textString
     */
    private void showToastDialog(String textString) {
        ToastDialog toastDialog = new ToastDialog(getContext().getApplicationContext());

        Component component = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_example_custom_text, null, false);
        Text text = (Text) component.findComponentById(ResourceTable.Id_text);
        text.setText(textString);

        toastDialog.setContentCustomComponent(component);
        toastDialog.show();
    }
}
